//
//  FMTextField.swift
//  iPhone
//
//  Created by Toj on 8/28/22.
//

import UIKit

enum FMTextFieldStyle {
    case titleLeft
    case titleTop
}

protocol FMTextFieldDelegate: NSObjectProtocol {
    
    func textFieldEditingValided(_ view: FMTextField, string: String) -> Bool
    
    func textFieldEditingChange(_ view: FMTextField, text: String, stringValue: String)
    
    func textFieldDidBeginEditing(_ view: FMTextField)
    
    func textFieldDidEndEditing(_ view: FMTextField)
    
    func textFieldShouldReturn(_ view: FMTextField) -> Bool
    
    func textFieldShouldClear(_ view: FMTextField) -> Bool
}

extension FMTextFieldDelegate {
    
    func textFieldEditingValided(_ view: FMTextField, string: String) -> Bool {
        return true
    }
    
    func textFieldEditingChange(_ view: FMTextField, text: String, stringValue: String) { }
    
    func textFieldDidBeginEditing(_ view: FMTextField) { }
    
    func textFieldDidEndEditing(_ view: FMTextField) { }
    
    func textFieldShouldReturn(_ view: FMTextField) -> Bool { return true }
    
    func textFieldShouldClear(_ view: FMTextField) -> Bool { return true }
}

class FMTextField: UIView {
    
    weak var delegate: FMTextFieldDelegate?
    
    var style: FMTextFieldStyle = .titleTop
    var lineHeight: CGFloat = 1
    
    var titleNormalColor: UIColor = .black { didSet {
        titleLabel.textColor = titleNormalColor
    } }
    var lineNormalColor: UIColor = .black { didSet {
        lineView.backgroundColor = lineNormalColor
    } }
    
    private(set) var isHighlight = false
    var titleHighlightColor: UIColor? { didSet {
        guard titleHighlightColor != nil else {
            return
        }
        isHighlight = true
    } }
    var lineHighlightColor: UIColor? { didSet {
        guard lineHighlightColor != nil else {
            return
        }
        isHighlight = true
    } }
  
    var charFormatType: String.SPFormatterType = .none
    var maxCharCount = 0 { didSet {
        if isCharCount {
            isCharCount = maxCharCount > 0
        }
        guard maxCharCount > 0 else {
            charFormatType = .none
            return
        }
        maxCharLabel.text = "0/\(maxCharCount)"
    } }
    
    var isCharCount: Bool = true { didSet {
        maxCharLabel.isHidden = !isCharCount
    } }
    
    var textSeparator = " "
    var leftMargin: CGFloat = 0
    
    var text: String {
        get {
            return textField.text ?? ""
        }
        
        set {
            textField.text = newValue
        }
    }
    var textValue: String {
        get { return stringValue }
        set { stringValue = newValue }
    }
    var stringValue: String {
        get {
            if textSeparator.isEmpty {
                return text
            }
            
            return text.replacingOccurrences(of: textSeparator, with: "")
        }
        
        set {
            let textString = editingFormat(string: newValue)
            textField.text = textString
        }
    }
    
    private func editingFormat(string text: String) -> String {
        var string = text
        //guard isCharCount else { return text }
        
        let count = string.count
        if isCharCount, count > maxCharCount {
            let startIndex = string.startIndex
            let middleIndex = string.index(startIndex, offsetBy: maxCharCount)
            let range = middleIndex..<string.endIndex
            string.removeSubrange(range)
        }
        
        maxCharLabel.text = "\(count)/\(maxCharCount)"
        let ftext = string.cm_numberFormat(format: charFormatType, separator: textSeparator)
        return ftext
    }
    
    private func textFieldEditingChange(with sender: UITextField) {
        let string = sender.text?.replacingOccurrences(of: textSeparator, with: "") ?? ""
        let text = editingFormat(string: string)
        sender.text = text
        delegate?.textFieldEditingChange(self, text: text, stringValue: string)
    }
    
    var rightView: UIView? = nil { didSet {
        guard let view = rightView else { return }
        addSubview(view)
    } }
    
    private(set) lazy var titleLabel: UILabel = {
        let view = UILabel()
        return view
    }()
    
    private(set) lazy var textField: UITextField = {
        let view = DCTextField()
        view.dc_isDisableCopy = true
        view.backgroundColor = .clear
        // 边框
        view.borderStyle = .none
        // 是否纠错
        view.autocorrectionType = .no
        // 首字母大写
        view.autocapitalizationType = .none
        
        view.delegate = self
        return view
    }()
    
    private(set) lazy var lineView: UIView = {
        let view = UIView()
        view.backgroundColor = "#DDDDDD".to_color
        return view
    }()
    
    private(set) lazy var maxCharLabel: UILabel = {
        let view = UILabel()
        return view
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        setupMakeAddSubviews()
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        setupMakeLayoutSubviews()
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    private let defaultFont = UIFont.systemFont(ofSize: 12)
}

// MARK: - 初始化
extension FMTextField {
    
    private func setupMakeAddSubviews() {
        
        addSubview(titleLabel)
        addSubview(textField)
        addSubview(lineView)
        addSubview(maxCharLabel)
    }
    
    private func setupMakeLayoutSubviews() {
        var cheight = CGFloat.zero
        if isCharCount {
            cheight = "9/9".cm_stringOneLineHeight(font: maxCharLabel.font)
            maxCharLabel.snp.makeConstraints { make in
                make.bottom.right.equalTo(self)
                make.height.equalTo(cheight)
            }
        }
       
        let font = textField.font ?? defaultFont
        let theight = "9".cm_stringOneLineHeight(font: font)
        
        var size = CGSize.zero
        if let view = rightView {
            size = view.frame.size
        }
        let right = size.width + 5 // margin = 5
        
        if style == .titleTop {
            titleLabel.snp.makeConstraints { (make) in
                make.top.left.right.equalTo(self)
            }
            
            let titleText = titleLabel.text ?? ""
            let top = titleText.isEmpty ? 0 : 12
            textField.snp.makeConstraints { (make) in
                make.left.equalTo(leftMargin)
                make.top.equalTo(titleLabel.snp.bottom).offset(top)
                make.height.equalTo(theight)
                make.right.equalTo(-right)
            }
        }
        
        if style == .titleLeft {
            titleLabel.snp.makeConstraints { (make) in
                make.left.equalTo(leftMargin)
                make.top.equalTo(self)
                make.bottom.equalTo(self).inset(cheight)
            }
            
            textField.snp.makeConstraints { (make) in
                make.left.equalTo(titleLabel.snp.right).offset(5)
                make.centerY.equalTo(titleLabel)
                make.height.equalTo(theight)
                make.right.equalTo(-right)
            }
        }
        
        rightView?.snp.makeConstraints { make in
            make.right.equalTo(self)
            make.centerY.equalTo(textField)
            make.height.equalTo(size.height)
            make.width.equalTo(size.width)
        }
        
        lineView.snp.makeConstraints { (make) in
            make.left.right.equalTo(self)
            make.height.equalTo(lineHeight)
            make.bottom.equalTo(textField.snp.bottom).offset(10)
        }
    }
}

extension FMTextField: UITextFieldDelegate {
    
    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        
        // 删除
        if string.isEmpty {
            let result = textField.tf_delete(shouldChangeCharactersIn: range, formatType: charFormatType, separator: textSeparator)
            textFieldEditingChange(with: textField)
            return result
        }
        
        // 非数字过滤掉, 系统有个bug 如果返回false光标也跳转count位
        let isValid = delegate?.textFieldEditingValided(self, string: string) ?? true
        guard isValid else { return false }
        
        // 输入
        let result = textField.tf_insert(shouldChangeCharactersIn: range, replacementString: string, maxLength: maxCharCount, formatType: charFormatType, separator: textSeparator)

        textFieldEditingChange(with: textField)

        return result
    }
    
    // 进入编辑状态
    func textFieldDidBeginEditing(_ textField: UITextField) {
        delegate?.textFieldDidBeginEditing(self)
        guard isHighlight else { return }
        
        titleLabel.textColor = titleHighlightColor
        lineView.backgroundColor = lineHighlightColor
    }
    
    // 完成编辑
    func textFieldDidEndEditing(_ textField: UITextField) {
        delegate?.textFieldDidEndEditing(self)
        guard isHighlight else { return }
        
        titleLabel.textColor = titleNormalColor
        lineView.backgroundColor = lineNormalColor
    }
    
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        textField.endEditing(true)
        let result = delegate?.textFieldShouldReturn(self) ?? true
        return result
    }
    
    func textFieldShouldClear(_ textField: UITextField) -> Bool {
        delegate?.textFieldEditingChange(self, text: "", stringValue: "")
        let result = delegate?.textFieldShouldClear(self) ?? true
        return result
    }
}

/* DC = disable copy
 * 可以禁用copy文本框
 */
private class DCTextField: UITextField {
    
    private let dc_disableSelector: [Selector] = [
        #selector(UIResponderStandardEditActions.paste(_:)),
        #selector(UIResponderStandardEditActions.select(_:)),
        #selector(UIResponderStandardEditActions.selectAll(_:))
    ]
    
    public var dc_isDisableCopy = false
    open override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
        if dc_isDisableCopy {
            if dc_disableSelector.contains(action) { return false }
        }
        return super.canPerformAction(action, withSender: sender)
    }
}
